package com.wande.dataplatform.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wande.common.core.utils.StringUtils;
import com.wande.common.mybatis.core.page.PageQuery;
import com.wande.common.mybatis.core.page.TableDataInfo;
import com.wande.dataplatform.domain.QualityReport;
import com.wande.dataplatform.domain.vo.QualityReportVo;
import com.wande.dataplatform.mapper.QualityReportMapper;
import com.wande.dataplatform.service.IQualityReportService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据质量报告服务实现
 *
 * @author wande
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class QualityReportServiceImpl implements IQualityReportService {

    private final QualityReportMapper qualityReportMapper;

    @Override
    public TableDataInfo<QualityReportVo> queryPageList(QualityReportVo vo, PageQuery pageQuery) {
        LambdaQueryWrapper<QualityReport> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(StringUtils.isNotBlank(vo.getReportType()), QualityReport::getReportType, vo.getReportType());
        wrapper.eq(vo.getTaskId() != null, QualityReport::getTaskId, vo.getTaskId());
        wrapper.eq(vo.getTableId() != null, QualityReport::getTableId, vo.getTableId());
        wrapper.eq(StringUtils.isNotBlank(vo.getStatus()), QualityReport::getStatus, vo.getStatus());
        wrapper.eq(vo.getProjectId() != null, QualityReport::getProjectId, vo.getProjectId());
        wrapper.orderByDesc(QualityReport::getExecuteTime);
        Page<QualityReport> page = qualityReportMapper.selectPage(pageQuery.build(), wrapper);
        Page<QualityReportVo> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        voPage.setRecords(BeanUtil.copyToList(page.getRecords(), QualityReportVo.class));
        return TableDataInfo.build(voPage);
    }

    @Override
    public QualityReportVo queryById(Long id) {
        QualityReport entity = qualityReportMapper.selectById(id);
        return BeanUtil.toBean(entity, QualityReportVo.class);
    }

    @Override
    public QualityReportVo queryLatestByTaskId(Long taskId) {
        LambdaQueryWrapper<QualityReport> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(QualityReport::getTaskId, taskId);
        wrapper.orderByDesc(QualityReport::getExecuteTime);
        wrapper.last("LIMIT 1");
        QualityReport entity = qualityReportMapper.selectOne(wrapper);
        return BeanUtil.toBean(entity, QualityReportVo.class);
    }

    @Override
    public List<QualityReportVo> queryByTableId(Long tableId, LocalDate startDate, LocalDate endDate) {
        LambdaQueryWrapper<QualityReport> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(QualityReport::getTableId, tableId);
        if (startDate != null) {
            wrapper.ge(QualityReport::getExecuteTime, LocalDateTime.of(startDate, LocalTime.MIN));
        }
        if (endDate != null) {
            wrapper.le(QualityReport::getExecuteTime, LocalDateTime.of(endDate, LocalTime.MAX));
        }
        wrapper.orderByDesc(QualityReport::getExecuteTime);
        List<QualityReport> list = qualityReportMapper.selectList(wrapper);
        return BeanUtil.copyToList(list, QualityReportVo.class);
    }

    @Override
    public Map<String, Object> getQualityTrend(Long tableId, LocalDate startDate, LocalDate endDate) {
        List<QualityReportVo> reports = queryByTableId(tableId, startDate, endDate);

        Map<String, Object> trend = new HashMap<>();
        List<String> dates = new ArrayList<>();
        List<BigDecimal> scores = new ArrayList<>();
        List<Long> problemRows = new ArrayList<>();

        for (QualityReportVo report : reports) {
            dates.add(report.getExecuteTime().toLocalDate().toString());
            scores.add(report.getQualityScore());
            problemRows.add(report.getProblemRows() != null ? report.getProblemRows() : 0L);
        }

        trend.put("dates", dates);
        trend.put("scores", scores);
        trend.put("problemRows", problemRows);

        return trend;
    }

    @Override
    public Map<String, Object> getDimensionStats(Long tableId) {
        // 获取最新报告
        LambdaQueryWrapper<QualityReport> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(QualityReport::getTableId, tableId);
        wrapper.orderByDesc(QualityReport::getExecuteTime);
        wrapper.last("LIMIT 1");
        QualityReport entity = qualityReportMapper.selectOne(wrapper);
        QualityReportVo latestReport = BeanUtil.toBean(entity, QualityReportVo.class);

        Map<String, Object> stats = new HashMap<>();
        if (latestReport != null && StringUtils.isNotBlank(latestReport.getDimensionStats())) {
            try {
                Map<String, Object> dimensionStats = JSONUtil.toBean(latestReport.getDimensionStats(), Map.class);
                stats.putAll(dimensionStats);
            } catch (Exception e) {
                log.error("解析维度统计失败", e);
            }
        }

        return stats;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Long id) {
        return qualityReportMapper.deleteById(id) > 0;
    }
}
